package com.boot.dongli.config;

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author: lkz
 * @Title: RabbitConfig
 * @Description: TODO
 * @Date: 2023/10/16 15:10
 */
@Configuration
public class RabbitConfig {


    //配置：备用交换机
    @Bean
    public DirectExchange altNormalExchange(){
        return ExchangeBuilder // 默认为持久化的，默认不自动删除
                .directExchange("alt.normal.exchange") // 交换机的名字
                .alternate("alt.exchange") //设置备用交换机 alternate-exchange
                .build();
    }

    @Bean
    public Queue queueAltNormal(){
        return QueueBuilder.durable("alt.normal.queue").build();
    }

    @Bean
    public Binding bindingAltNormal(DirectExchange altNormalExchange,Queue queueAltNormal){
        return BindingBuilder.bind(queueAltNormal).to(altNormalExchange).with("alt.normal");
    }

    @Bean //备用交换机
    public FanoutExchange alternateExchange(){
        return ExchangeBuilder.fanoutExchange("alt.exchange").build();
    }

    @Bean
    public Queue alternateQueue(){
        return QueueBuilder.durable("alt.queue").build();
    }

    @Bean
    public Binding bindingAlternate(FanoutExchange alternateExchange,Queue alternateQueue){
        return BindingBuilder.bind(alternateQueue).to(alternateExchange);
    }


    //配置结束：备用交换机

   // 配置：延迟队列插件配置
    /**
     * 创建自定义交换机
     * @return
     */
    @Bean
    public CustomExchange customExchange() {
        Map<String, Object> arguments =new HashMap<>();
        arguments.put("x-delayed-type","direct"); //放一个参数
//        CustomExchange(String name, String type, boolean durable, boolean autoDelete, Map<String, Object> arguments)
        return  new CustomExchange("plugins.exchange","x-delayed-message",true,false,arguments);

    }

    @Bean
    public Queue queuePlugin() {
        //方式2 建造者
        return QueueBuilder
                .durable("plugin_queue") //队列名称
                .build();
    }

    @Bean
    public Binding binding(CustomExchange customExchange, Queue queuePlugin) {
        //绑定，也指定路由key，加noargs 方法
        return BindingBuilder.bind(queuePlugin).to(customExchange).with("plugin").noargs();
    }
   // 配置结束：延迟队列插件配置

    //配置  死信队列和正常使用一个交换机
    @Bean
    public DirectExchange directNorDlxExchange() {
        return ExchangeBuilder.directExchange("normal.dlx.exchange").build();
    }

    @Bean
    public Queue queueNormalDlx() {
        //方式1 new Queue 的方式
//        Map<String, Object> arguments = new HashMap<>();
//        arguments.put("x-message-ttl", 25000); //消息过期时间 25秒
//        return new Queue(queueName, true, false, false, arguments);
        //方式2 建造者
        return QueueBuilder
                .durable("normal.dlx.normalQueue") //队列名称
                .ttl(10000) //队列的过期时间
                .deadLetterExchange("normal.dlx.exchange") //设置死信交换机 ，设置相同的交换机
                .deadLetterRoutingKey("normal.dlx.dlx.error") //设置死信路由key，设置成交换机和死信队列绑定key
                .build();
    }

    /**
     * 上面通过设置队列的过期时间 容易产生消息堆积问题
     *  下面这个队列模拟不在队列上设置消息，在发送消息本身设置过期时间
     * @return
     */
    @Bean
    public Queue queueNormalDlxTwo() {
        //方式1 new Queue 的方式
//        Map<String, Object> arguments = new HashMap<>();
//        arguments.put("x-message-ttl", 25000); //消息过期时间 25秒
//        return new Queue(queueName, true, false, false, arguments);
        //方式2 建造者
        return QueueBuilder
                .durable("normal.dlx.normalQueueTwo") //队列名称
                .deadLetterExchange("normal.dlx.exchange") //设置死信交换机 ，设置相同的交换机
                .deadLetterRoutingKey("normal.dlx.dlx.error") //设置死信路由key，设置成交换机和死信队列绑定key
                .build();
    }

    @Bean
    public Binding bindingNormalDlxTwo(DirectExchange directNorDlxExchange, Queue queueNormalDlxTwo) {
        return BindingBuilder.bind(queueNormalDlxTwo).to(directNorDlxExchange).with("normal.dlx.normalTwo.x");
    }

    @Bean
    public Binding bindingNormalDlx(DirectExchange directNorDlxExchange, Queue queueNormalDlx) {
        return BindingBuilder.bind(queueNormalDlx).to(directNorDlxExchange).with("normal.dlx.normal.x");
    }

    @Bean
    public Queue normalDlxDlxQueue() {
        return QueueBuilder.durable("normal.dlx.dlxQueue").build();
    }

    @Bean
    public Binding bindingNormalDlxDlx(DirectExchange directNorDlxExchange, Queue normalDlxDlxQueue) {
        return BindingBuilder.bind(normalDlxDlxQueue).to(directNorDlxExchange).with("normal.dlx.dlx.error");

    }
    //配置:结束  死信队列和正常使用一个交换机



    // 配置：消费者拒绝消息不进行重新投递
    @Bean
    public DirectExchange normalAutoExchange(){
        return ExchangeBuilder.directExchange("auto.normal.exchange").build();
    }
    @Bean
    public Queue normalAutoQueue(){
        Map<String, Object> arguments =new HashMap<>();
        //其他参数配置
       // arguments.put("x-overflow","reject-publish"); //队列的溢出行为，删除头部，改成拒绝发布
       // arguments.put("x-single-active-consumer",true); //单一消费者 同一个消息只能被一个消费者消费
       // arguments.put("x-max-length-bytes",100); //设置消息队列的容量
       // arguments.put("x-max-priority",10); //设置队列的优先级为10
        // 重点：：设置这两个参数
        //设置对列的死信交换机
        arguments.put("x-dead-letter-exchange","auto.ttl.exchange");
        //设置死信路由key，要和死信交换机和死信队列绑定key一模一样，因为死信交换机是直连交换机
        arguments.put("x-dead-letter-routing-key","auto.error");
        return QueueBuilder.durable("auto.normal.queue")
                .withArguments(arguments) // 设置对列过期时间
                .build();
    }
    @Bean
    public Binding bindingAutoNormal(DirectExchange normalAutoExchange,Queue normalAutoQueue){
        return BindingBuilder.bind(normalAutoQueue).to(normalAutoExchange).with("auto.normal");
    }
    @Bean
    public DirectExchange dlxAutoExchange(){
        return ExchangeBuilder.directExchange("auto.ttl.exchange").build();
    }
    @Bean
    public Queue dlxAutoQueue(){
        return QueueBuilder.durable("auto.ttl.queue").build();
    }
    @Bean
    public Binding bindingDlxAuto(DirectExchange dlxAutoExchange,Queue dlxAutoQueue){
        return BindingBuilder.bind(dlxAutoQueue).to(dlxAutoExchange).with("auto.error");
    }



    // 配置结束：消费者拒绝消息不进行重新投递

    // 配置：队列长度限制进入死信队列
    /**
     * 正常交换机 type=direct
     * @return
     */
    @Bean
    public DirectExchange normalLengthExchange(){
        return ExchangeBuilder.directExchange("length.normal.exchange").build();
    }

    /**
     * 正常队列
     * @return
     */
    @Bean
    public Queue normalQueue(){
        Map<String, Object> arguments =new HashMap<>();
        //设置对列的最大长度
        arguments.put("x-max-length",5);
        // 重点：：设置这两个参数
        //设置对列的死信交换机
        arguments.put("x-dead-letter-exchange","length.ttl.exchange");
        //设置死信路由key，要和死信交换机和死信队列绑定key一模一样，因为死信交换机是直连交换机
        arguments.put("x-dead-letter-routing-key","length.error");
        return QueueBuilder.durable("length.normal.queue")
                .withArguments(arguments) // 设置对列过期时间
                .build();
    }

    /**
     * 正常交换机和正常队列绑定
     * @param normalLengthExchange
     * @param normalQueue
     * @return
     */
    @Bean
    public Binding bindingLengthNormal(DirectExchange normalLengthExchange,Queue normalQueue){
        return BindingBuilder.bind(normalQueue).to(normalLengthExchange).with("length.normal");
    }

    /**
     * 死信交换机 type=direct
     * @return
     */
    @Bean
    public DirectExchange dlxLengthExchange(){
        return ExchangeBuilder.directExchange("length.ttl.exchange").build();
    }

    /**
     * 死信队列
     * @return
     */
    @Bean
    public Queue dlxLengthQueue(){
        return QueueBuilder.durable("length.ttl.queue").build();
    }

    /**
     * 死信交换机和死信队列绑定
     * @param dlxLengthExchange
     * @param dlxLengthQueue
     * @return
     */
    @Bean
    public Binding bindingDlxLength(DirectExchange dlxLengthExchange,Queue dlxLengthQueue){
        return BindingBuilder.bind(dlxLengthQueue).to(dlxLengthExchange).with("length.error");
    }

    // 配置：队列长度限制进入死信队列 结束


     // 过期消息发送私信队列
    /**
     * 声明交换机
     */
    @Bean
    public DirectExchange normalDlxOneExchange(){
        return ExchangeBuilder.directExchange("dlx.one.normalExchange").build();
    }
    /**
     * 声明正常队列
     */
    @Bean
    public Queue normalDlxOneQueue(){
        Map<String,Object> arg=new HashMap<>();
        arg.put("x-message-ttl",5000); //设置对列的过期时间为5秒 //删除改行 可以在发送消息的时候设置
        // 重点：：设置这两个参数
        arg.put("x-dead-letter-exchange","dlx.one.ttlExchange"); //设置对列的死信交换机
        arg.put("x-dead-letter-routing-key","error"); //设置死信路由key，要和死信交换机和死信队列绑定key一模一样
        return QueueBuilder.durable("dlx.one.normalQueue").withArguments(arg).build();
    }

    /**
     * 队列绑定交换机
     */
    @Bean
    public Binding bindingOneNormal(DirectExchange normalDlxOneExchange, Queue normalDlxOneQueue){
        return BindingBuilder.bind(normalDlxOneQueue).to(normalDlxOneExchange).with("order");
    }

    /**
     * 死信交换机
     * @return
     */
    @Bean
    public DirectExchange dlxExchange(){
        return ExchangeBuilder.directExchange("dlx.one.ttlExchange").build();
    }

    /**
     * 死信队列
     * @return
     */
    @Bean
    public Queue dlxQueue(){
        return QueueBuilder.durable("dlx.one.ttlQueue").build();
    }

    /**
     * 死信交换机和死信队列绑定
     * @param dlxExchange
     * @param dlxQueue
     * @return
     */
    @Bean
    public Binding bindingDlx(DirectExchange dlxExchange,Queue dlxQueue){
        return BindingBuilder.bind(dlxQueue).to(dlxExchange).with("error");
    }

    // 过期消息发送配置结束

    // 消息时间过期
    @Bean
    public DirectExchange directExchange(){
        return ExchangeBuilder.directExchange("ttl.one.exchange").build();
    }

    @Bean
    public Queue queue(){
        return QueueBuilder.durable("ttlOne_queue").build();
    }

    @Bean
    public Binding binding(DirectExchange directExchange, Queue queue){
        return BindingBuilder.bind(queue).to(directExchange).with("info");
    }
    // 消息时间过期结束

    // 设置队列层面过期
    @Bean
    public DirectExchange directTwoExchange() {
        return ExchangeBuilder.directExchange("ttl.two.exchange").build();
    }

    @Bean
    public Queue twoQueue() {
        //方式1 new Queue 的方式
        Map<String, Object> arguments = new HashMap<>();
        arguments.put("x-message-ttl", 15000); //消息过期时间
        return new Queue("ttl.two.queue", true, false, false, arguments);
        //方式2 建造者
//        return QueueBuilder
//                .durable(queueName)
//                .withArguments(arguments).
//                build();
    }

    @Bean
    public Binding twoBinding(DirectExchange directExchange, Queue queue) {
        return BindingBuilder.bind(queue).to(directExchange).with("info");
    }

    // 设置队列层面过期结束



    


}
